package com.ruoyi.gateway.filter;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import io.netty.buffer.ByteBufAllocator;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * 对前端GET和PUT方法传来的body进行解密
 *
 * @author shenli
 * @version v0.1.0
 * @since 2025/10/16 18:53
 */
@Component
public class DecryptFilter implements GlobalFilter, Ordered {

  @Value("${rsa.private.key}")
  private String rsaPrivateKey;

  private static final String HEADER_PUBLIC_WORD = "public-word";

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    System.out.println("运行 DecryptFilter：" + exchange.getRequest().getURI());

    final List<String> keyList = exchange.getRequest().getHeaders().get(HEADER_PUBLIC_WORD);

    if (keyList == null || keyList.isEmpty()) {
      return chain.filter(exchange);
    }

    //shenli 25-10-17 14:10 以下解密前端的body
    final HttpMethod method = exchange.getRequest().getMethod();
    if (method != HttpMethod.POST && method != HttpMethod.PUT) {
      return chain.filter(exchange);
    }

    final Flux<DataBuffer> body = exchange.getRequest().getBody();

    // 获取原始请求体并转换为字节数组
    final Mono<byte[]> bodyMono = DataBufferUtils.join(body).map(dataBuffer -> {
      final byte[] bytes = new byte[dataBuffer.readableByteCount()];
      dataBuffer.read(bytes);
      DataBufferUtils.release(dataBuffer);
      return bytes;
    });

    return bodyMono.flatMap(originalBytes -> {
      // 处理解密逻辑
      String originalBodyStr = new String(originalBytes, StandardCharsets.UTF_8);

      // AES解密（去掉body中可能存在的引号）
      final String key = keyList.get(0);

      final byte[] decode = Base64Decoder.decode(key);
      final byte[] keyByte = new RSA(rsaPrivateKey, null).decrypt(decode, KeyType.PrivateKey);
      final String keyStr = new RSA(rsaPrivateKey, null).decryptStr(key, KeyType.PrivateKey);
      final String decryptStr = new AES(Mode.ECB, Padding.PKCS5Padding, keyByte).decryptStr(originalBodyStr.replace("\"", ""));
      System.out.println("decryptStr = " + decryptStr);

      // 创建新的DataBuffer
      NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
      DataBuffer newBuffer = bufferFactory.wrap(decryptStr.getBytes(StandardCharsets.UTF_8));

      // 创建请求装饰器
      ServerHttpRequest modifiedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
        @Override
        @NonNull
        public Flux<DataBuffer> getBody() {
          return Flux.just(newBuffer);
        }
      };

      // 继续执行下一个过滤器
      return chain.filter(exchange.mutate().request(modifiedRequest).build());
    }).then();
  }

  @Override
  public int getOrder() {
    return -300;
  }
}
